package search;

import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;

import stemmer.PorterStemmer;
import stemmer.PorterStemmerExeption;

import net.barashev.seclub.io.BufferManager;
import net.barashev.seclub.io.file.FileManager;

public class SearchEngine {
	private static final int maxResSize = 100;
	private FileManager fileMgr;
	private BufferManager bufferMgr;
	private PorterStemmer stemmer;
	private Intersections intersections;
	private final int memorySize;
	private Sorter sorter;
	

	public SearchEngine(FileManager fileMgr,int memorySize) {
		this.fileMgr = fileMgr;
		this.bufferMgr = new BufferManager(4, 4096);
		this.stemmer = new PorterStemmer();
		this.memorySize=memorySize;
		this.intersections=new Intersections(memorySize/4);
		this.sorter=new Sorter();
	}

	public List<Integer> search(String query) throws IOException {
		LinkedList<String> phraseList = toPhrases(query);
		Iterator<String> iterator = phraseList.iterator();
		DiscBufferedIntegerList res;
		if (iterator.hasNext()) {
			res = phraseSearch(iterator.next());
			while (iterator.hasNext()) {
				res = intersections.intersect(res, phraseSearch(iterator.next()));
			}
		} else {
			return null;
		}
		return sorter.sort(res,maxResSize);
	}

	private DiscBufferedIntegerList phraseSearch(String phrase) throws IOException {
		StringTokenizer tkzr = new StringTokenizer(phrase);
		String curr = null;
		try {
			curr = stemmer.stem(tkzr.nextToken());
		} catch (PorterStemmerExeption e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		DiscBufferedIntegerList res = null;
		if (tkzr.hasMoreTokens()) {
			DiscBufferedIdWOList resWithOcc = new DiscBufferedIdWOList(fileMgr, bufferMgr, curr, false, memorySize/4);
			while (tkzr.hasMoreTokens()) {
				try {
					resWithOcc = intersections.intersect(resWithOcc,new DiscBufferedIdWOList(fileMgr, bufferMgr, stemmer.stem(tkzr.nextToken()), false, memorySize/4));
				} catch (PorterStemmerExeption e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			res = resWithOcc.extractIds();
			
		} else {
			res = new DiscBufferedIntegerList(fileMgr, bufferMgr, curr, false, memorySize/4);
		}
		return res;
	}

	private static LinkedList<String> toPhrases(String query) {
		LinkedList<String> res = new LinkedList<String>();
		boolean inquotes = false;
		String curr = "";
		for (int i = 0; i < query.length(); i++) {
			if (query.charAt(i) == '"') {
				if (inquotes & (curr.length() > 0)) {
					res.add(curr);
					curr = "";
				}
				inquotes = !inquotes;
			} else {
				if (inquotes) {
					curr = curr + query.charAt(i);
				} else {
					if (query.charAt(i) == ' ') {
						if (curr.length() > 0) {
							res.add(curr);
						}
						curr = "";
					} else {
						curr = curr + query.charAt(i);
					}
				}
			}
		}
		if (curr.length() > 0) {
			res.add(curr);
		}
		return res;
	}
}
